package com.yumeng.framework.auth.security.authentication.custom;

import com.yumeng.common.data.enums.AuthClientType;
import com.yumeng.common.helper.AssertHelper;
import com.yumeng.common.helper.BaseEnumHelper;
import com.yumeng.common.utils.HttpUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;

import java.io.IOException;

/**
 * 自定义AuthFilter 基于AbstractAuthenticationProcessingFilter
 * @author wxd
 * @date 2025/4/8 16:41
 */
public abstract class CustomAbstractAuthenticationProcessingFilter  extends AbstractAuthenticationProcessingFilter {

    /** 是否json方式接受参数 */
    private boolean jsonParam = false;
    /** 仅支持post方式 */
    private boolean postOnly = true;
    /** 参数名-客户端类型 */
    private String clientTypeParameter = "clientType";

    protected CustomAbstractAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
        super(requiresAuthenticationRequestMatcher);
    }

    protected CustomAbstractAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher, AuthenticationManager authenticationManager) {
        super(requiresAuthenticationRequestMatcher, authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (this.postOnly && !HttpUtils.isPost(request)) {
            throw new AuthenticationServiceException("认证方法不支持该访问方式：" + request.getMethod());
        }
        String clientTypeStr = null;//客户端类型
        AbstractAuthenticationToken authRequest = null;
        if (!this.jsonParam){
            clientTypeStr = request.getParameter(this.clientTypeParameter);
            authRequest = obtainAuthenticationToken(request);
        }else {
            if (!HttpUtils.isJsonMediaType(request)){
                throw new AuthenticationServiceException("认证参数格式异常：" + request.getContentType());
            }
            //解析请求体中的 JSON 参数
/*            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            username = user.getUsername();
            username = (username != null) ? username.trim() : "";
            password = user.getPassword();
            password = (password != null) ? password : "";*/
            clientTypeStr = "待实现";
            authRequest = obtainAuthenticationTokenForJson(request);
        }
        AuthClientType clientType = StringUtils.isNotBlank(clientTypeStr) ?
                BaseEnumHelper.getEnum(AuthClientType.class, Integer.parseInt(clientTypeStr), true) : AuthClientType.getDefault();
        setDetails(request, authRequest, clientType);
        Authentication authResult = this.getAuthenticationManager().authenticate(authRequest);
        return authResult;
    }

    private void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest, AuthClientType clientType) {
        request.setAttribute(CustomWebAuthenticationDetails.REQUEST_KEY_AUTH_CLIENT_TYPE, clientType);
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public void setJsonParam(boolean jsonParam) {
        this.jsonParam = jsonParam;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public void setClientTypeParameter(String clientTypeParameter) {
        AssertHelper.assertNotBlank(clientTypeParameter, "ClientType parameter must not be empty or null");
        this.clientTypeParameter = clientTypeParameter;
    }

    /**
     * 获取AuthenticationToken
     * @param request
     * @return
     */
    protected abstract AbstractAuthenticationToken obtainAuthenticationToken(HttpServletRequest request);

    /**
     * 获取AuthenticationToken（json方式）
     * @param request
     * @return
     */
    protected abstract AbstractAuthenticationToken obtainAuthenticationTokenForJson(HttpServletRequest request);
}
